Modular Linux Kernel

Link and Unlink Modules at Runtime

Author: David Montaño

Agenda

Why should I care? (as a High Level Developper)

Linux Kernel Quick Review

  • History
  • Monolithic
  • Compiled and Statically linked
  • Kernel Threads and User Threads
  • Virtual File System
  • Hardware Dependency
  • Linux Versions
  • Linux Startup Process

Loadable Kernel Modules

  • Kernel Modules
  • Not your daily C / Not libc
  • Where are they?
  • When are they loaded?
  • Linux Kernel Ring
  • List Loaded Modules
  • Which ones is my Hardware using?
  • Get Module Info
  • Load a Module
  • Unload a Module
  • Blacklisting Kernel Modules
  • Tainted Kernel

Do it Yourself: Compile Your Own Linux Kernel Module

  • Hello Kernel Module
  • MP3 Rickroll Kernel Module

References

Why should I care? (as a High Level Developper)

Linux Quick Review

History

Monolithic

  • One large and complex Program
  • Several Logical Different Components
  • Many Unix variants are Monolithic *

Compiled and Statically Linked

  • Static Kernel Modules
  • Dynamic Kernel Modules

Kernel Threads and User Threads

  • Preemptive Theads
  • Multiprocessor Support
  • Tow types of Threads:
    • Kernel Threads
    • User Threads: Multithreaded Application Support

Virtual Filesystem Swith

  • Specifies an interface (or a "contract") between the kernel and a concrete file system.
  • It is easy to add support for new file system types to the kernel simply by fulfilling the contract.

Hardware Dependency

  • Distinction between hardware-dependent and hardware-independent code.
  • These directories include 23 subdirectories that correspond to the different types of hardware platforms supported
    • arch
    • include

Linux Versions

Linux Versions

  • Linux GRSEC
  • Linux ZEN
  • Linux AUFS (advanced multi layered unification filesystem)
  • Linux Apparmor
  • Linux BFS (Brain Fuck Scheduler - created by Con Kolivas for desktop computers with fewer than 4096 cores)
  • etc...

Linux Startup Process

  1. Bootloader Phase
    • BIOS: Master Boot Record code
    • UEFI: Linux Kernel Can be executed directly
  2. Kernel Loading Phase: loads binary
  3. Kernel Startup Phase: executes kernel binary
    • Load Kernel Data Structures
    • Load Kernel Modules
      • initrd: initial RAM Disk
      • initramfs: initial RAM File System
      • mkinitcpio
    • Starts init process (SysV init|Systemd|Upstart|runit)

Example Bootloader Configuration File: grub.cfg

Kernel Modules

Modules are pieces of code that can be loaded and unloaded into the kernel upon demand. They extend the functionality of the kernel without the need to reboot the system.

The device driver is one type of module. It allows the kernel to access hardware connected to the system.

Not your daily C / Not libc

  • The kernel doesn't use libc.
  • The kernel defines some functions like: printk.
  • So Kernel Modules are limited: e.g. NO FLOATING POINT ARITHMETIC

Where are they?

/usr/lib/modules/kernel_release

When are they loaded?

  • During Kernel Startup Phase: mkinitcpio
    • /etc/modprobe.d/*
  • During first process initialization: e.g. udev(part of systemd)
    • coding parallelism to provide a potential performance advantage versus loading these modules serially.
    • does not always load modules in the same order on each boot.
    • /etc/udev/rules.d/*

Linux Kernel Ring


	[david@JANUS]$ dmesg -T
	    					

Used to write the kernel messages in Linux and other Unix-like operating systems to standard output (which by default is the display screen).

List Loaded Modules


	[david@JANUS]$ lsmod
	    					

Trivial program which nicely formats the contents of the /proc/modules, showing what kernel modules are currently loaded.

Which ones is my Hardware using?


	[david@JANUS:~]$ lspci -k
							

Get Module Info


	[david@JANUS]$ modinfo <a kernel module>
	    					

Lists each attribute of the module in form fieldname : value, for easy reading. The filename is listed the same way (although it's not really an attribute)..

Load a Module (Without Dependencies)


	[david@JANUS]$ insmod <a kernel module>
	    					

Trivial program to insert a module into the kernel. Most users will want to use modprobe instead, which is more clever and can handle module dependencies..

Unload a Module


	[david@JANUS]$ rmmod <a kernel module>
	    					

Trivial program to remove a module (when module unloading support is provided) from the kernel. Most users will want to use modprobe with the -r option instead..

Load/Unload a Module (With Dependencies)


	[david@JANUS]$ modprobe [-r] <a kernel module>
	    					

Intelligently adds or removes a module from the Linux kernel..

Blacklisting Kernel Modules


/etc/modprobe.d/blacklist.conf
...
install module_name /bin/false
...

/etc/modprobe.d/<somefile>.conf
...
# Do not load the 'pcspkr' module on boot.
blacklist pcspkr
...

/boot/grub/grub.cfg
...
linux   /boot/vmlinuz-linux root=UUID=26f245ba-c23f-4ad7-bba8-a235c89b4e97 rw  rcutree.rcu_idle_gp_delay=1 modprobe.blacklist=modname1,modname2,modname3
...

Tainted Kernel

  • When the Kernel is in a state that is unsupported by the community
  • The kernel may become tainted for any of several reasons:
    • Use of a proprietary (or non-GPL compatible) kernel module
    • Staging drivers: part of the kernel source code but not fully tested
    • etc..

Kernel Module Fun

  • Julia Evans: Systems Programming, Hacker (Linux, Scala, Python), talks, etc.
  • Github Repository: https://github.com/jvns/kernel-module-fun
  • Dependencies: Linux Kernel Headers from your current Kernel version
  • 
    [david@JANUS:~]$ uname -a
    [david@JANUS:~]$ yaourt | apt-get install | yum -i | linux-headers-$(uname -r)
    

Do It Yourself: Hello Kernel Module

Makefile

  • Compiles 5 Kernel Objects.
  • Uses another Makefile in the build directory of the specific Kernel Version

obj-m += hello.o
obj-m += hello-packet.o
obj-m += rootkit.o
obj-m += rickroll.o
obj-m += excited_virus.o

all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

hello.c

  • Compiles 5 Kernel Objects.
  • Uses another Makefile in the build directory of the specific Kernel Version

#include <linux/module.h>    // included for all kernel modules
#include <linux/kernel.h>    // included for KERN_INFO
#include <linux/init.h>      // included for __init and __exit macros

static int __init hello_init(void)
{
    printk(KERN_INFO "Hello, hacker school!!!\n");
    return 0;    // Non-zero return means that the module couldn't be loaded.
}

static void __exit hello_cleanup(void)
{
  printk(KERN_INFO "I am dead.\n");
}

module_init(hello_init);
module_exit(hello_cleanup);

Compiling the Kernel Modules

Loading the hello Kernel Module


	[david@JANUS:~]$ sudo insmod hello.ko
	[david@JANUS:~]$ sudo rmmod hello.ko
	

Do It Yourself: MP3 Rickroll Kernel Module

This Kernel Module changes the mp3 file you open with any program on your system with the one we want to hear. :)

Rickroll Steps

  1. Get your song: rickroll.mp3
  2. Change rickroll.c source code (path of your song!!)

rickroll.c


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/syscalls.h>
#include <linux/string.h>


MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kamal Marhubi");
MODULE_DESCRIPTION("Rickroll module");

static char *rickroll_filename = "/home/david/linux/modules/chica/kernel-module-fun/rickroll.mp3";

...

Loading the MP3 Rickroll Kernel Module

Load the module.

	[david@JANUS:~]$ sudo insmod rickroll.ko
	
Open your favorite music player and listen any MP3 file.
Then unload the module.

	[david@JANUS:~]$ sudo rmmod hello.ko
	

Kernel Module Interface: init and exit functions


static int __init rickroll_init(void)
{
    if(!rickroll_filename) {
        printk(KERN_ERR "No rick roll filename given.");
        return -EINVAL;  /* invalid argument */
    }
...
static void __exit rickroll_cleanup(void)
{
    printk(KERN_INFO "Ok, now we're gonna give you up. Sorry.\n");

    /* Restore the original sys_open in the table */
    DISABLE_WRITE_PROTECTION;
    sys_call_table[__NR_open] = (unsigned long *) original_sys_open;
    ENABLE_WRITE_PROTECTION;
}
...
module_init(rickroll_init);
module_exit(rickroll_cleanup);

References